package com.example.sentinel.infrastructure.handler;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.example.sentinel.domain.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class SentinelExceptionHandler {
    // 用于存储当前请求的限流和熔断状态
    private static final ThreadLocal<BlockInfo> BLOCK_INFO_THREAD_LOCAL = new ThreadLocal<>();

    // 处理限流和熔断
    public static Result handleBlock(BlockException ex) {
        // 判断异常类型并记录
        boolean isFlowBlocked = ex instanceof FlowException;
        boolean isDegradeBlocked = ex instanceof DegradeException;
        BLOCK_INFO_THREAD_LOCAL.set(new BlockInfo(isFlowBlocked, isDegradeBlocked));

        return Result.error(500, "服务繁忙，请稍后再试");
    }

    // 处理业务异常,如空指针异常,会降级处理
    public static Result handleFallback(Throwable ex) {
        // 非Sentinel异常，清空ThreadLocal
        BLOCK_INFO_THREAD_LOCAL.remove();
        log.error("服务异常，降级处理");
        return Result.error(500, "服务暂时不可用");
    }

    // 获取当前请求的限流和熔断状态
    public static BlockInfo getBlockInfo() {
        return BLOCK_INFO_THREAD_LOCAL.get();
    }

    // 移除当前请求的限流和熔断状态
    public static void removeBlockInfo() {
        BLOCK_INFO_THREAD_LOCAL.remove();
    }

    // 静态内部类，用于存储限流和熔断状态
    public static class BlockInfo {
        private final boolean isFlowBlocked;
        private final boolean isDegradeBlocked;

        public BlockInfo(boolean isFlowBlocked, boolean isDegradeBlocked) {
            this.isFlowBlocked = isFlowBlocked;
            this.isDegradeBlocked = isDegradeBlocked;
        }

        public boolean isFlowBlocked() {
            return isFlowBlocked;
        }

        public boolean isDegradeBlocked() {
            return isDegradeBlocked;
        }
    }
}    